<template>
  <div class="mx-info" v-show="currentVisible">
    <div class="mx-info-window" :style="currentStyle" ref="window">
      <div class="mx-info-window-top">
        <a class="mx-info-window-title" href="javascript:;">{{ currentTitle }}</a>
        <div class="mx-info-window-close" @click="onClose"><img src="./iw_close.png"/></div>
      </div>
      <div class="mx-info-window-content">
        <component
          :sources="sources"
          :prop="currentProp"
          v-if="currentComponent"
          :is="currentComponent"/>
      </div>
      <img class="mx-info-window-img" src="./iw_tail.png">
    </div>
  </div>
</template>

<script>
import common, { ComponentName, EventName, Emitter } from "../common";
import _ from "lodash";

export default {
  componentName: ComponentName.info,
  mixins: [Emitter],
  props: {
    show: {},
    sources: {},
    map: {},
    options: {},
    zoom: {},
    category: {}
  },
  data() {
    return {
      position: { x: 0, y: 0 }
    };
  },
  created() {
    this.updatePosition();
    this.$on(EventName.updatePosition, this.updatePosition);
  },
  computed: {
    currentLayer() {
      return this.options && this.options.layer ? this.options.layer : {}
    },
    currentMarker() {
      return this.currentLayer.marker || {}
    },
    currentProp() {
      return this.options.prop || {};
    },
    currentInfoWindow() {
      return this.options.layer.infoWindow || {};
    },
    currentPoint() {
      return this.options.point || [0, 0];
    },
    currentVisible() {
      return (
        this.show &&
        this.currentLayerShow &&
        this.currentCategoryShow &&
        this.currentMarkerShow
      );
    },
    currentLayerShow() {
      if (!this.currentLayer.zoom) return true
      let [start, end] = this.currentLayer.zoom
      return this.zoom >= Number(start) && this.zoom <= Number(end)
    },
    currentCategoryShow() {
      let category = this.currentMarker.category
      if (!category) return true
      if (typeof category === 'string') {
        category = _.get(this.currentProp, category)
        return this.category.indexOf(category) > -1
      } else if (typeof category === 'function') {
        return category.call(this, this.currentProp, this.category)
      } else {
        return true
      }
    },
    currentMarkerShow() {
      let zoom = this.currentMarker.zoom
      if (!zoom) return true
      if (typeof zoom === 'function') {
        zoom = zoom.call(this, this.currentProp)
      } else if (typeof zoom === 'string') {
        zoom = _.get(this.currentProp, zoom)
      }
      let [start, end] = zoom
      return this.zoom >= Number(start) && this.zoom <= Number(end)
    },
    currentComponent() {
      return this.currentInfoWindow.component;
    },
    currentTitle() {
      let title = this.currentInfoWindow.title;
      if (!title) return "";
      if (typeof title === "function") {
        return title.call(this, this.currentProp);
      } else {
        return _.get(this.currentProp, title);
      }
    },
    currentSize() {
      let [width, height] = common
        .case(this.currentInfoWindow.size)
        .array(val => val)
        .default([330, 256]);
      width = Number(width);
      height = Number(height);
      return [width, height];
    },
    currentOffset() {
      let [dx, dy] = common
        .case(this.currentInfoWindow.offset)
        .array(val => val)
        .function(val => val.call(this, this.currentProp))
        .default([0, 0]);
      dx = Number(dx);
      dy = Number(dy);
      return [dx, dy];
    },
    currentStyle() {
      let pointer = this.currentPoint;
      if (!pointer) {
        return { display: "none" };
      } else {
        let { x, y } = this.position;
        let [width, height] = this.currentSize;
        let [dx, dy] = this.currentOffset;
        return {
          position: "absolute",
          left: `${x}px`,
          bottom: `${-y}px`,
          width: `${width}px`,
          height: `${height}px`,
          transform: `translate3d(${-width / 2 + 29 + dx}px, -${dy + 31}px, 0px)`
        };
      }
    }
  },
  methods: {
    updatePosition() {
      this.position = this.map.pointToPixel(...this.currentPoint);
    },
    onClose() {
      this.dispatch(ComponentName.map, EventName.closeInfoWindow);
    }
  }
};
</script>

<style type="text/stylus" lang="stylus" rel="stylesheet/stylus">
.mx-info {
  position: absolute;
  width: 0;
  left: 0;
  height: 0;
  top: 0;
  z-index: 10;
  overflow: visible;

  &-window {
    display: flex;
    flex-direction: column;
    position: absolute;
    background-color: #ffffff;
    box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), 0 0 6px 0 rgba(0, 0, 0, 0.04);
    border-radius: 4px;
    user-select: none;

    &-top {
      font-size: 15px;
      height: 36px;
      line-height: 36px;
      overflow: hidden;
      padding-left: 8px;
      color: #fff;
      font-weight: bold;
      border-radius: 2px 2px 0 0;
      background-color: #1e96e7;
      user-select: text;
      cursor: default;
    }

    &-title {
      font-weight: normal;
      color: #ffffff;
    }

    &-close {
      float: right;
      user-select: none;
      cursor: pointer;
      overflow: hidden;
      padding: 0 10px;
    }

    &-content {
      flex: 1;
      overflow: auto;
    }

    &-img {
      position: absolute;
      width: 58px;
      height: 31px;
      left: 50%;
      bottom: 0;
      margin-left: -29px;
      margin-bottom: -31px;
    }
  }
}
</style>
